import sys, pygame

pygame.init()

#region Fuctions
def clean_up_and_exit():
    pygame.quit()
    sys.exit()

def screen_pos_to_world_pos(pos: tuple[int, int]) -> tuple[int, int]:
    return (pos[0] + camera_pos[0], pos[1] + camera_pos[1])

def draw_rect(surface: pygame.surface.Surface, pos1: tuple[int, int], pos2: tuple[int, int], color: tuple[int, int, int] = (0, 0, 0), width: int = 0):
    size = (pos2[0] - pos1[0], pos2[1] - pos1[1])
    return pygame.draw.rect(surface, color, (
        pos1[0] if size[0] > 0 else pos1[0] - abs(size[0]),
        pos1[1] if size[1] > 0 else pos1[1] - abs(size[1]),
        abs(size[0]),
        abs(size[1])
    ), width)
#endregion

#region Engine stuff
fps = 60
fpsClock = pygame.time.Clock()

width, height = 640, 480
screen = pygame.display.set_mode((width, height), pygame.RESIZABLE)

antialias = False

camera_pos: list[int, int] = [0, 0]

left_clicked_pos: tuple[int, int] | None = None
middle_clicked_pos: tuple[int, int] | None = None
right_clicked_pos: tuple[int, int] | None = None

debug_ui_shown = False

prev_mouse_pos = (0, 0)
mouse_pos = pygame.mouse.get_pos()

render_enable = True
input_checks_enable = True
#endregion

#region UI
class UIElement:
    def __init__(self, x: int, y: int, width: int, height: int):
        self.x: int = x
        self.y: int = y
        self.width: int = width
        self.height: int = height
        self.state: str|None = None
        self.images: dict[str, pygame.surface.Surface] = {}
        self.init_images()

    def get_x(self) -> int:
        return self.x

    def get_y(self) -> int:
        return self.y

    def get_width(self) -> int:
        return self.width

    def get_height(self) -> int:
        return self.height

    def init_images(self):
        self.images['main'] = pygame.surface.Surface(self.get_rect())

    def get_rect(self) -> pygame.rect.Rect:
        return pygame.rect.Rect(
            self.get_x(),
            self.get_y(),
            self.get_width(),
            self.get_height()
        )

    def get_image(self) -> pygame.surface.Surface:
        return self.images['main']

    def handle_event(self, event: pygame.event.Event) -> bool:
        return False

class UIButton(UIElement):
    def __init__(self, x: int, y: int, text: str):
        self.x: int = x
        self.y: int = y
        self.width: int = 0
        self.height: int = 0
        self.text: str = text
        self.state: str|None = None
        self.images: dict[str, pygame.surface.Surface] = {}
        self.init_images()

    def init_images(self):
        font = pygame.font.Font(size=30)
        text_img = font.render(self.text, antialias, (0, 0, 0))
        self.width = text_img.get_width() + 20
        self.height = text_img.get_height() + 18
        image = pygame.surface.Surface((self.get_width(), self.get_height()), pygame.SRCALPHA)
        pygame.draw.rect(image, (255, 255, 255), (0, 0, self.get_width(), self.get_height()), 0, 10)
        pygame.draw.rect(image, (200, 200, 200), (0, 0, self.get_width(), self.get_height()), 5, 10)
        image.blit(text_img, (10, 10))
        self.images['main'] = image

class UIManager:
    pass
#endregion

cur_tool = 'cursor'

#region Tool Buttons
tool_font = pygame.font.Font(size=30)
cursor_tool_image = tool_font.render('Cursor', antialias, (0, 0, 0), (200, 200, 200))
cursor_tool_image = cursor_tool_image.convert_alpha()
cursor_tool_image.set_alpha(200)
rectangle_tool_image = tool_font.render('Rectangle', antialias, (0, 0, 0), (200, 200, 200))
rectangle_tool_image = rectangle_tool_image.convert_alpha()
rectangle_tool_image.set_alpha(200)
#endregion

#region Debug
debug_screen_space = 10
debug_font = pygame.font.Font(size=20)
debug_screen_label = debug_font.render('Debug Information', antialias, (0, 0, 0))
#endregion

temp_ui_button = UIButton(100, 100, 'UIButton Test')

while True:
    events = pygame.event.get()
    for event in events:
        prev_mouse_pos = mouse_pos
        mouse_pos = pygame.mouse.get_pos()

        if event.type == pygame.QUIT:
            clean_up_and_exit()
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_q:
                clean_up_and_exit()
        elif event.type == pygame.VIDEORESIZE:
            screen_width = event.w
            screen_height = event.h
        elif event.type == pygame.ACTIVEEVENT:
            render_enable = event.state == 1
            input_checks_enable = bool(event.gain)
    if render_enable:
        screen.fill((255, 255, 255))

    for event in events:
        if input_checks_enable:
            if event.type == pygame.MOUSEBUTTONDOWN:
                if event.button == 1:
                    left_clicked_pos = mouse_pos
                elif event.button == 2:
                    middle_clicked_pos = mouse_pos
                elif event.button == 3:
                    right_clicked_pos = mouse_pos
            elif event.type == pygame.MOUSEBUTTONUP:
                if event.button == 1:
                    left_clicked_pos = None
                elif event.button == 2:
                    middle_clicked_pos = None
                elif event.button == 3:
                    right_clicked_pos = None
            elif event.type == pygame.MOUSEMOTION:
                if event.buttons[0]:
                    match cur_tool:
                        case 'cursor':
                            if left_clicked_pos:
                                if render_enable:
                                    draw_rect(screen, left_clicked_pos, mouse_pos, (0, 0, 0), 1)
                if event.buttons[1]:
                    pass
                if event.buttons[2]:
                    camera_pos[0] += mouse_pos[0] - prev_mouse_pos[0]
                    camera_pos[1] += mouse_pos[1] - prev_mouse_pos[1]
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_F3:
                    debug_ui_shown = not debug_ui_shown

        if render_enable:
            # WORLD

            # UI
            screen.blit(temp_ui_button.get_image(), temp_ui_button.get_rect())

            screen.blit(cursor_tool_image, (5, 5))
            screen.blit(rectangle_tool_image, (10 + cursor_tool_image.get_width(), 5))

            if debug_ui_shown:
                camera_pos_img = debug_font.render(f'Camera positon: X={camera_pos[0]} Y={camera_pos[1]}', antialias, (0, 0, 0))
                bg_size = [0, 0]

                bg_size[0] = max(bg_size[0], debug_screen_label.get_width() + (debug_screen_space * 2))
                bg_size[0] = max(bg_size[0], camera_pos_img.get_width() + (debug_screen_space * 2))

                bg_size[1] += debug_screen_label.get_height() + debug_screen_space
                bg_size[1] += camera_pos_img.get_height() + debug_screen_space
                bg_size[1] += debug_screen_space

                debug_screen = pygame.Surface(bg_size)
                debug_screen = debug_screen.convert_alpha()
                debug_screen.fill((200, 200, 200))

                debug_screen.blit(debug_screen_label, ((bg_size[0] // 2) - (debug_screen_label.get_width() // 2), debug_screen_space))
                debug_screen.blit(camera_pos_img, (debug_screen_space, camera_pos_img.get_height() + (debug_screen_space * 2)))

                debug_screen.set_alpha(200)
                screen.blit(debug_screen, (debug_screen_space, screen.get_height() - debug_screen.get_height() - debug_screen_space))

        pygame.display.flip()
